#include "ray.h"

#include <cmath>

bool e_null_ray(const ray3f ray)
{
	return e_null_pnt(ray.origin) && e_null_vec(ray.dir);
}

ray3f create_ray_between_2_points(const pnt3f a, const pnt3f b, const float margin)
{
	vec3f dir = normalize(b - a);
	return ray3fc(a + dir * margin, dir);
}

ray3f create_ray_from_pos_dir(const pnt3f pos, const vec3f dir, const float margin)
{
	return ray3fc(pos + dir * margin, dir);
}

ray3f create_reflected_ray(const ray3f ray, const pnt3f p, const vec3f N, const float margin)
{
	vec3f R = ray.dir-2.f*dot(ray.dir,N)*N;
	return ray3fc(p+R*margin,R);
}

ray3f create_refraction_ray(const ray3f ray, const pnt3f p, 
	const vec3f N, const float refraction_index, const float margin)
{
	ray3f refraction_ray = ray3fc( origin(), zero_vec3f() );

	if (refraction_index > 0.f)
	{
		float rindex = refraction_index;
		float n = 1.f / rindex;

		float cosI = -dot( N, ray.dir );
		float cosT2 = 1.f - n * n * (1.f - cosI * cosI);

		if (cosT2 > 0.f)
		{
			vec3f T = (n * ray.dir) + (n * cosI - sqrt( cosT2 )) * N;
			refraction_ray = ray3fc(p+T*margin,T);
		}
	}

	return refraction_ray;
}